/*
* 页面组件用这个WrappedTable包装之后的页面可以拿到ref
* 页面组件用这个WrappedTable.create包装之后的页面可以拿到this.props里的pub方法和数据
*/
import React, { Component, Fragment, Children } from 'react';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';
import { pub_rowSelectionToStore, pub_getAllTableData, pub_isLoading } from '@/Redux/ActionTypes/public/BaseTable/publicActionCreator.js';

export const EditableContext = React.createContext();
let searchRef = React.createRef(null);  // 搜索栏的ref
let tableRef = React.createRef(null);   // table表格的ref

class WrappedTable extends Component {
  static create = (markName) => (WrappedComponent) => { // WrappedComponent是被包装的组件

    //高阶组件，高阶函数
    const mapStateToProps = (state, ownProps) => {
      return {
        pub_rowSelection: state.baseTable.pub_rowSelection, // 拿到选中的当行数据,行配置类型为radio或者checkbox时适用
        pub_allTableData: state.baseTable.pub_allTableData, // 拿到表格所有数据
        pub_isLoading: state.baseTable.pub_isLoading, // 是否拿到表格数据的标识
      }
    }
    const mapDispatchToProps = (dispatch) => ({
      pub_getRowSelection(...rest) {
        return dispatch(pub_rowSelectionToStore(...rest)); // 把选中的当行数据发送到store
      },
      pub_sendAllTableData(...rest) {
        return dispatch(pub_getAllTableData(...rest)); // 把所有表格数据更新发送到store
      },
      pub_changeisLoading(...rest) {
        return dispatch(pub_isLoading(...rest)); // 把标志是否获取表格数据的isLoading标识修改
      }
    })
    @connect(mapStateToProps, mapDispatchToProps) // 装饰器
    @withRouter
    class InnerClass extends Component {
      constructor(props) {
        super(props);
        const { location: { pathname } } = this.props;// 写在这里的目的是为了将来一个页面可能会有多个表单。 将来在这里改一下标识即pathname就可以
        this.markId = markName ? markName : pathname;// 模态框时不会执行
      }

      render() {
        const { location: { pathname } } = this.props;// 写在这里的目的是为了将来一个页面可能会有多个表单。 将来在这里改一下标识即pathname就可以
        this.markId = markName ? markName : pathname;// 模态框时执行这里
        //let tableCom = tableRef.current; // 拿到baseTable的ref，之后可能会有用
        let searchCom = searchRef.current; // 拿到searchForm的ref
        let config = {
          pub_markId: this.markId,
        }
        if (searchCom) { // 如果已经把ref连接上
          const { handleSumbit, searchFunc } = searchCom;
          config['pub_getAllData'] = handleSumbit; // 搜索栏根据搜索条件发送请求的函数,pub_getAllData是提供给开发页面的人在编辑或者删除时可以重新获取表格数据的方法
          config['pub_searchFunc'] = searchFunc; // 暴露请求函数，以便在没有 searchForm 的情况下更改请求体获取数据
        }
        return (
          <WrappedComponent {...this.props}
            {...config}
          /> // 被包装的组件可以拿到公共组件的方法和数据
        )
      }
    }
    return InnerClass;
  }
  // 这里可以用深度遍历，而不用限制Search和Table必须在BaseClass的第一层子组件之中
  addRefToChildren = () => {
    let childList = this.props.children;
    let list = Children.map(childList, child => {
      let props = child.props;
      if (props.changeTableData && props.changeSearchLimit) { // 判断是搜索栏组件还是table表格
        return React.cloneElement(child, { ref: props.tableConfig ? tableRef : searchRef })
      } // table一定有changeTableData和changeSearchLimit和tableConfig
      // searchForm有changeTableData和changeSearchLimit
      // 借此条件来判断是哪一个然后加上ref
      return child;
    })
    return list;
  }
  render() {
    return (
      <Fragment>
        <EditableContext.Provider value={this.props.form}>
          {this.addRefToChildren()}
        </EditableContext.Provider>
      </Fragment>
    )
  }
}
export default WrappedTable;